﻿using System;
using System.Linq;
using Framework.Repository;
using Framework.Repository.Testing;
using Framework.Tests.Repository.Entities;
using Xunit;

namespace Framework.Tests.Repository
{
    public class CascadeAllConventionTest
    {
        [Fact]
        public void Should_have_dependency_into_same_table_is_component_feature()
        {
            using (var integrationTest = new IntegrationTest(new AutoMappingAssemblyProvider().AddEntityAssemblyOfType<SuperUser>()))
            {
                var repository = integrationTest.CreateRepository<Society>();

                repository.Save(new Society("ClemCorp", new Address("toto", 1, 65000), null, new SocietyNumber(12345)));

                Assert.NotNull(repository.Where(x => x.Name == "ClemCorp").First());
            }
        }

        [Fact]
        public void Should_have_one_table_per_subclass_inheritance_for_person_and_one_table_per_subclass_and_baseclass_for_user()
        {
            using (var integrationTest = new IntegrationTest(new AutoMappingAssemblyProvider().AddEntityAssemblyOfType<SuperUser>()))
            {
                var repository = integrationTest.CreateRepository<SuperUser>();

                repository.Save(new SuperUser("Clem", null, "Admin"));

                Assert.NotNull(repository.Where(x => x.Name == "Clem").First());
            }
        }

        /// <summary>
        ///   Tests with feature : 
        ///   - Force One to One in Society override Automapping
        ///   - One table per sub class Entity inheritance
        ///   - Do not use Entity attribute on base class like Person
        ///   - Component Mapping : 
        ///   - Society have a dependency One to One on Address, mapping is component
        ///   - All Properties of Address Mapping are stored into Society table
        /// </summary>
        [Fact]
        public void Test_CascadeAllConvention_Succeed()
        {
            using (var integrationTest = new IntegrationTest(new AutoMappingAssemblyProvider().AddEntityAssemblyOfType<SuperUser>()))
            {
                var boss = new Boss("Clem");
                var society = new Society("ClemCorp", new Address("Allée des pins", 8, 77210), boss,
                    new SocietyNumber(12345));
                var user = new SuperUser("Clem", society, "Admin");
                user.Rights.Add(new Right("sa"));

                Console.WriteLine("Insert");
                var userRepo = integrationTest.CreateRepository<User>();
                var superUserRepo = integrationTest.CreateRepository<SuperUser>();

                userRepo.Save(user);

                Console.WriteLine("Fetching super user");
                var actualUser = superUserRepo.Where(u => u.Name == "Clem").First();

                Assert.NotNull(actualUser);
                Assert.True(actualUser.Rights.Count == 1);
                Assert.True(actualUser.Rights.First().Name == "sa");
                Assert.True(actualUser.Society.Name == "ClemCorp");

                Assert.True(actualUser.Role == "Admin");

                Console.WriteLine("Fetching Right");

                var rightRipo = integrationTest.CreateRepository<Right>();
                var actualRight = rightRipo.Where(r => r.Name == "sa").First();
                Assert.NotNull(actualRight);
                Assert.True(actualRight.Name == "sa");

                Console.WriteLine("Fetching Society");
                var societyRepo = integrationTest.CreateRepository<Society>();
                var actualSociety = societyRepo.Where(s => s.Name == "ClemCorp").First();
                Assert.NotNull(actualSociety);
                Assert.True(actualSociety.Name == "ClemCorp");

                Console.WriteLine("Delete super user");
                superUserRepo.Delete(actualUser);

                Assert.False(superUserRepo.Where(u => u.Name == "Clem").Any());
                Assert.False(rightRipo.Where(r => r.Name == "sa").Any());
                Assert.False(societyRepo.Where(s => s.Name == "ClemCorp").Any());
            }
        }
    }
}